package ca.ubc.cs304.library.gui;



import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.GroupLayout.Alignment;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.UIManager;

import ca.ubc.cs304.library.actions.ClerkActions;
import ca.ubc.cs304.library.gui.helper.*;

import ca.ubc.cs304.library.sql.OracleDatabaseWrapper;


public class LibWindow {
	// Singleton Object
	private static LibWindow me;
	
	private static final String SUBJECT [] = {" ", "Fiction", "Horror", "Classics", "Comedy", "Computer"};
	private static final String MENU [] = {"New", "Edit"};	
	private static final String MENU_NEW [] = {"Connect", "Disconnect"};	
	private static final String MENU_EDIT [] = {"Clear All Fields"};	
	
	private static final int MAX_CPNT = 8;	
	private static final int MAX_X = 835;	// 
	private static final int MAX_Y = 600;
	
	private static final int CPNT_HEIGHT = 30;
	private static final int BUTN_WIDTH = 140;
	private static final int LIST_WIDTH = 380;
	private static final int TEXT_WIDTH = 380;
	
	private static final int CPNT_INDENT = 20;
	private static final int EXEC_X = 660;
	private static final int EXEC_Y = 450;
	
	private static final String ADD_BORROWER = "Add Borrower";
	private static final String CHECK_OVERDUE = "Check Overdue";
	private static final String CHECK_OUT_ITEM = "Check-out Item";
	private static final String PROCESS_RETURN = "Process Return";

	private static final String [] BRW_BUTN = {"Search Book", "Check Account", "Place Hold", "Pay Fine", "Execute"};
	private static final String [] LIB_BUTN = {"Add Book", "Remove Book", "Remove Borrower ", "Check-out Report", "Popularity Report", "Execute"};
	private static final String [] CLK_BUTN = {ADD_BORROWER, CHECK_OUT_ITEM, PROCESS_RETURN, CHECK_OVERDUE, "Execute"};
		
	
	private String action;

	final private JFrame frame = new JFrame();	
	final private JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
	
	// ------------------------------------------------------------------------------------------------------
	// Menu Components
	// ------------------------------------------------------------------------------------------------------	
	final private JMenuBar menuBar = new JMenuBar();
	final private JMenu [] mnMenu = new JMenu [2];
	final private JMenu [] mnNewItem = new JMenu [2];
	final private JMenu [] mnEditItem = new JMenu [1];
	
	
	// ------------------------------------------------------------------------------------------------------
	// Borrower Components
	// ------------------------------------------------------------------------------------------------------

	final protected JPanel brwQryTab 		= new JPanel();
	final protected JLabel [] brwLabl 		= new JLabel [MAX_CPNT];
	final protected JTextField [] brwText 	= new JTextField [MAX_CPNT];
	final private JTabbedPane brwTab 		= new JTabbedPane(JTabbedPane.TOP);	
	final private JButton [] brwButton 		= new JButton [5];
	final private LibTableModel brwModel1	= new LibTableModel();
	final private LibTableModel brwModel2	= new LibTableModel();
	final private LibTableModel brwModel3	= new LibTableModel();
	final private JTable brwTable1			= new JTable (brwModel1);
	final private JTable brwTable2			= new JTable (brwModel2);
	final private JTable brwTable3			= new JTable (brwModel3);
	final private JScrollPane brwScroll1		= new JScrollPane(brwTable1);
	final private JScrollPane brwScroll2		= new JScrollPane(brwTable2);
	final private JScrollPane brwScroll3		= new JScrollPane(brwTable3);

	final private JComboBox brwSubjList		= new JComboBox();

	
	// ------------------------------------------------------------------------------------------------------	
	// Librarian Components
	// ------------------------------------------------------------------------------------------------------
	
	final protected JPanel libQryTab 			= new JPanel();	
	final protected JLabel [] libLabl 			= new JLabel [MAX_CPNT];
	final protected JTextField [] libText 		= new JTextField [MAX_CPNT];
	final private JTabbedPane libTab 			= new JTabbedPane(JTabbedPane.TOP);	
	final private JButton [] libButton 			= new JButton [6];
	final private JTable libTable 				= new JTable ();
	final private JScrollPane libScroll			= new JScrollPane(libTable);
	
	final private JComboBox libSubjList			= new JComboBox();
	final private DefaultListModel libListModel	= new DefaultListModel();
	final private JList libMultiList			= new JList(libListModel);
	final private JScrollPane libScrollList 	= new JScrollPane(libMultiList);
	
	// ------------------------------------------------------------------------------------------------------
	// Clerk Components
	// ------------------------------------------------------------------------------------------------------
	public static final String USER_TYPE_FACULTY = "Faculty";
	public static final String USER_TYPE_STAFF = "Staff";
	public static final String USER_TYPE_STUDENT = "Student";
	
	final private JTabbedPane clkTab = new JTabbedPane(JTabbedPane.TOP);
	final private JPanel clkQryTab = new JPanel();
	
	final private LibTableModel clkModel 	= new LibTableModel();
	final private JTable clkTable = new JTable (clkModel);
	final private JScrollPane clkScroll		= new JScrollPane(clkTable);
	
	final protected JTextField [] clkText = new JTextField [MAX_CPNT];
	final protected JComboBox [] clkList = new JComboBox [MAX_CPNT];
	final protected JLabel [] clkLabl = new JLabel [MAX_CPNT];
	
	final private JButton [] clkButton = new JButton [5];
	
	// Clerk layout member variables - DO NOT MODIFY
	private final int NUMBER_OF_CALL_NUMBERS = 6;
	public static final int CALL_NUMBER_INDEX = 0;
	public static final int COPY_NUMBER_INDEX = 1;
	
	final private JTextField sinOrStudentNumberTextField 	= new JTextField(20);
	final private JTextField nameTextField					= new JTextField(20);
	final private JPasswordField passwordTextField			= new JPasswordField(20);
	final private JTextField addressTextField				= new JTextField(20);
	final private JTextField phoneNumberTextField			= new JTextField(20);
	final private JTextField emailAddressTextField			= new JTextField(20);
	final private JTextField expiryDateTextField			= new JTextField(20);
	final private JComboBox userTypeComboBox				= new JComboBox();
	
	final private JTextField borrowerIdTextField			= new JTextField(34);
	final private JTextField[] callNumberTextFields			= new JTextField[NUMBER_OF_CALL_NUMBERS];
	final private JTextField[] copyNumbersTextFields		= new JTextField[NUMBER_OF_CALL_NUMBERS];
	
	// External Objects
	private OracleDatabaseWrapper sql;
	private LibLogin login;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			LibWindow window = LibWindow.getInstance();
			window.frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}


		try {
			LibWindow window = LibWindow.getInstance();
			window.frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}

		//	}
		//});

	}


	synchronized public static  LibWindow getInstance () {
		if(me == null) {
			me = new LibWindow();
			return me;
		} else {
			return me;
		}
	}
	
    public JFrame getFrame() {
		return this.frame;
	}
    
    public JScrollPane getClkScroll() {
    	return this.clkScroll;
    }
    
    public JTextField getSinOrStudentNumberTextField() {
		return sinOrStudentNumberTextField;
	}
    
	public JTextField getNameTextField() {
		return nameTextField;
	}
    
	public JPasswordField getPasswordTextField() {
		return passwordTextField;
	}
    
	public JTextField getAddressTextField() {
		return addressTextField;
	}
    
	public JTextField getPhoneNumberTextField() {
		return phoneNumberTextField;
	}
    
	public JTextField getEmailAddressTextField() {
		return emailAddressTextField;
	}
    
	public JTextField getExpiryDateTextField() {
		return expiryDateTextField;
	}
    
	public JComboBox getUserTypeComboBox() {
		return userTypeComboBox;
	}

	public JTextField getBorrowerIdTextField() {
		return borrowerIdTextField;
	}
	
	public JTextField[] getCallNumTextFields() {
		return callNumberTextFields;
	}
	
	public JTextField[] getCopyNumberTextFields() {
		return copyNumbersTextFields;
	}
	

	public LibWindow() {		
		initialize();
	}

	
	private void initialize() {
        // Select the Nimbus look and feel if it's available on this system
		for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
			if ("nimbus".equalsIgnoreCase(info.getName())) {
				try {
					UIManager.setLookAndFeel(info.getClassName());
				} catch (Exception e) {
					// Exception? no big deal :-) Java reverts to it's default look anyways.
				}
				break;
			}
		}
		
		
		frame.setTitle("University Library Application v1.0");
		frame.setResizable(false);
		frame.setBounds(200, 100, MAX_X, MAX_Y);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
		frame.setJMenuBar(menuBar);
		
	
		initMenuBar();
		
		frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
		tabbedPane.addTab("Borrower", null, brwTab, null);
		tabbedPane.addTab("Librarian", null, libTab, null);
		tabbedPane.addTab("Clerk", null, clkTab, null);
	
		// Borrower Tab		
		brwTab.addTab("Query", null, brwQryTab, null);
		brwQryTab.setLayout(null);
		initBrwQryTab();
		
		
        // Librarian Tab
		libTab.addTab("Query", null, libQryTab, null);
		//libTab.addTab("Result", null, libScroll, null);	
		libQryTab.setLayout(null);
			
		initLibQryTab();
		libTable.setVisible(false);
		
		// Clerk Tab
		clkTab.addTab("Query", null, clkQryTab, null);
		clkQryTab.setLayout(null);
		initClkQryTab();
	}
	
	private void initMenuBar () {	
		for(int i = 0 ; i < mnMenu.length; i++) {
			mnMenu[i] = new JMenu(MENU[i]);
			menuBar.add(mnMenu[i]);
			
			switch(i) {
				// New Menu
				case 0:
					for(int j = 0; j < mnNewItem.length; j++) {
						mnNewItem[j] = new JMenu(MENU_NEW[j]);
						mnMenu[i].add(mnNewItem[j]);
					}					
					mnNewItem[1].setEnabled(false);
					
					break;
					
				// Edit Menu
				case 1:
					for(int j = 0; j < mnEditItem.length; j++) {
						mnEditItem[j] = new JMenu(MENU_EDIT[j]);
						mnMenu[i].add(mnEditItem[j]);
						mnEditItem[j].setEnabled(false);
					}
					break;

				default:
					break;
					
				}
			}
		

		// Connect
		mnNewItem[0].addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if(mnNewItem[0].isEnabled() == false) return;
				
				sql = OracleDatabaseWrapper.getInstance();
				login = new LibLogin(sql, frame, mnNewItem);
			}
		});

		
		// Disconnect
		mnNewItem[1].addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) { 
				if(mnNewItem[1].isEnabled() == false) return;		
				else if(sql.isConnected() == true) {
					//Custom button text
					Object[] options = {"Yes",
					                    "No"};
					int n = JOptionPane.showOptionDialog(frame,
					    "Would you like to disconnect?",
					    "Message",
					    JOptionPane.YES_NO_CANCEL_OPTION,
					    JOptionPane.QUESTION_MESSAGE,
					    null,
					    options,
					    options[0]);
					if(n == 0) {
						try {
							sql.closeConnect();
							frame.setTitle("University Library Application v1.0");
							mnNewItem[0].setEnabled(true);							
							mnNewItem[1].setEnabled(false);
							
						} catch (SQLException e) {
							JOptionPane.showMessageDialog(frame,
								    e.getMessage(),
								    "Error",
								    JOptionPane.ERROR_MESSAGE);
						}
					}
				}
			}
		});
		
		// Clear Fields
		mnEditItem[0].addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				clearFields();
			}
		});	
		
	}
	
	private void clearFields () {
		int num = 0;
		if (action == "generate report 1") {
			return;
		} else if(action == "add book") { // 5
			num = 5;
		}
		
		if(action == "search book" || 
			action == "place hold" ||
			action == "pay fine") {	// 3
			num = 3;
		} else if ( 
					action == "check account" ||
					action == "generate report 1" ||
					action == "generate report 2") { //2 
			num = 2;
		} else if (	
				action == "remove book" 	||
				action == "remove borrower"	||
				action == "generate report 2") {
			num = 1;
		} else {
			num = 0;
		}
		
		for(int i = 0 ; i < num ; i++) {
			brwText[i].setText("");
			libText[i].setText("");					
		}		
	}
	
	private void initBrwQryTab () {
		int x = 20;
		for(int i = 0 ; i < brwButton.length; i++) {
			brwButton[i] = new JButton ();
			brwButton[i].setText(BRW_BUTN[i]);

			if(i != brwButton.length - 1) {
				brwButton[i].setBounds(x, 20, BUTN_WIDTH, CPNT_HEIGHT);
				brwQryTab.add(brwButton[i]);
			} else {
				brwButton[i].setBounds(EXEC_X, EXEC_Y, BUTN_WIDTH, CPNT_HEIGHT);
				brwQryTab.add(brwButton[i]);				
			}
			
			x += BUTN_WIDTH + CPNT_INDENT;
		}
		
		int y = 65;
		for(int i = 0 ; i < brwText.length || i < brwLabl.length; i++) {
			brwText[i] = new JTextField ();
			brwText[i].setColumns(10);
			
			brwText[i].setBounds(420, y, TEXT_WIDTH, CPNT_HEIGHT);
			brwQryTab.add(brwText[i]);
			
			brwLabl[i] = new JLabel ();
			brwLabl[i].setBounds(20, y, LIST_WIDTH, CPNT_HEIGHT);
			brwLabl[i].setHorizontalAlignment(SwingConstants.CENTER);
			brwLabl[i].setFont(new Font(brwLabl[i].getFont().getName(), Font.BOLD, brwLabl[i].getFont().getSize()));
			brwQryTab.add(brwLabl[i]);		
			
			brwText[i].setVisible(false);
			brwLabl[i].setVisible(false);
			
			if(i == 2) {
				brwSubjList.setBounds(420, y, TEXT_WIDTH/2, CPNT_HEIGHT);
				
				for(int j = 0 ; j < SUBJECT.length ; j++) {
					brwSubjList.addItem(SUBJECT[j]);
				}
				
				brwSubjList.setVisible(false);
				brwQryTab.add(brwSubjList);
			}
			
			y += CPNT_HEIGHT + CPNT_INDENT;
		}
			
		
		// Search Book
		brwButton[0].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < brwButton.length ; i++) {
					if(i == 0) {
						brwButton[i].setEnabled(false);
					} else {
						brwButton[i].setEnabled(true);						
					}
				}
				
				action = "search book";
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields
				brwSubjList.setVisible(true);
				LibView.searchBook(brwLabl, brwText);
			}
		});
		
		// Check Account
		brwButton[1].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < brwButton.length ; i++) {
					if(i == 1) {
						brwButton[i].setEnabled(false);
					} else {
						brwButton[i].setEnabled(true);						
					}
				}
				
				action = "check account";
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields
				brwSubjList.setVisible(false);				
				LibView.checkAccount(brwLabl, brwText);		
			}
		});		
		
		// Place Hold
		brwButton[2].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < brwButton.length ; i++) {
					if(i == 2) {
						brwButton[i].setEnabled(false);
					} else {
						brwButton[i].setEnabled(true);						
					}
				}
				
				action = "place hold";		
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields		4
				brwSubjList.setVisible(false);				
				LibView.placeHold(brwLabl, brwText);		
			}
		});		

		// Pay Fine
		brwButton[3].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < brwButton.length ; i++) {
					if(i == 3) {
						brwButton[i].setEnabled(false);
					} else {
						brwButton[i].setEnabled(true);						
					}
				}
				
				action = "pay fine";		
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields	
				brwSubjList.setVisible(false);				
				LibView.payFine(brwLabl, brwText);				
			}
		});		

		// Execute
		brwButton[4].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(sql == null || sql.isConnected() == false) {
					JOptionPane.showMessageDialog(frame,
						    "No connection to database!",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);										
					return;
				}
				
				Boolean check = true;
				if(action == "search book") {
					try {
						check = LibExec.searchBook(brwLabl, brwText, brwTable1, brwSubjList, frame, sql);
						if (check) {		
							brwTab.remove(brwScroll1);
							brwTab.remove(brwScroll2);
							brwTab.remove(brwScroll3);
							brwTab.addTab("Results", null, brwScroll1, null);
							brwTable1.setVisible(true);
							brwTable2.setVisible(false);
							brwTable3.setVisible(false);
							JOptionPane.showMessageDialog(frame, "Search Done! See Results tab.");
						}
					} catch (SQLException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}

				} else if (action == "check account") {
					try {
						check = LibExec.checkAccount(brwLabl, brwText, brwTable1, brwTable2, brwTable3, frame, sql);
						if (check) {
							brwTab.remove(brwScroll1);
							brwTab.remove(brwScroll2);
							brwTab.remove(brwScroll3);
							brwTab.addTab("Borrowings", null, brwScroll1, null);
							brwTab.addTab("Holds", null, brwScroll2, null);
							brwTab.addTab("Fines", null, brwScroll3, null);
							brwTable1.setVisible(true);
							brwTable2.setVisible(true);
							brwTable3.setVisible(true);
							JOptionPane.showMessageDialog(frame, "Account Checked! See results tab.");
						}
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
							e.getMessage(),
						    "Error",
						    JOptionPane.ERROR_MESSAGE);
						
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}										
				} else if (action == "place hold") {
					try {
						check = LibExec.placeHold(brwLabl, brwText, brwTable1, sql);
						if (check) {
							brwTab.remove(brwScroll1);
							brwTab.remove(brwScroll2);
							brwTab.remove(brwScroll3);
							brwTab.addTab("Results", null, brwScroll1, null);
							brwTable1.setVisible(true);
							brwTable2.setVisible(false);
							brwTable3.setVisible(false);
							JOptionPane.showMessageDialog(frame, "Hold Placed!");
							
							return;
						}
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}					
				} else if (action == "pay fine") {
					try {

						check = LibExec.payFine(brwLabl, brwText, brwTable1, sql);
						if (check) {
							brwTab.remove(brwScroll1);
							brwTab.remove(brwScroll2);
							brwTab.remove(brwScroll3);
							brwTab.addTab("Results", null, brwScroll1, null);
							brwTable1.setVisible(true);
							brwTable2.setVisible(false);
							brwTable3.setVisible(false);
							JOptionPane.showMessageDialog(frame, "Fine Paid!");
							
							return;
						}
						
						

					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}					
				} 

				
				if(check != true) {
					brwTab.remove(brwScroll1);
					brwTab.remove(brwScroll2);
					brwTab.remove(brwScroll3);
					brwTable1.setVisible(false);
					brwTable2.setVisible(false);
					brwTable3.setVisible(false);
					JOptionPane.showMessageDialog(frame,
						    "Missing input field(s)",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);					
				}

			}	
		});		
	}

	private void initLibQryTab () {
		int x = 20;
		for(int i = 0 ; i < libButton.length; i++) {
			libButton[i] = new JButton ();
			libButton[i].setText(LIB_BUTN[i]);

			if(i != libButton.length - 1) {
				libButton[i].setBounds(x, 20, BUTN_WIDTH, CPNT_HEIGHT);
				libQryTab.add(libButton[i]);
			} else {
				libButton[i].setBounds(EXEC_X, EXEC_Y, BUTN_WIDTH, CPNT_HEIGHT);
				libQryTab.add(libButton[i]);				
			}
			
			x += BUTN_WIDTH + CPNT_INDENT;
		}	
	
		int y = 65;
		
		

		
		for(int i = 0 ; i < libText.length || i < libLabl.length; i++) {
			libText[i] = new JTextField ();
			libText[i].setColumns(10);
			
			libText[i].setBounds(420, y, TEXT_WIDTH, CPNT_HEIGHT);
			libQryTab.add(libText[i]);
			
			libLabl[i] = new JLabel ();
			libLabl[i].setBounds(20, y, LIST_WIDTH, CPNT_HEIGHT);
			libLabl[i].setHorizontalAlignment(SwingConstants.CENTER);
			libLabl[i].setFont(new Font(libLabl[i].getFont().getName(), Font.BOLD, libLabl[i].getFont().getSize()));
			libQryTab.add(libLabl[i]);		
			
			libText[i].setVisible(false);
			libLabl[i].setVisible(false);
			
			if(i == 0) {
				libSubjList.setBounds(420, y, TEXT_WIDTH/2, CPNT_HEIGHT);
				
				for(int j = 0 ; j < SUBJECT.length ; j++) {
					libSubjList.addItem(SUBJECT[j]);
				}
				
				libSubjList.setVisible(false);
				libQryTab.add(libSubjList);
			} else if (i == 5) {
				libMultiList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
				libMultiList.setLayoutOrientation(JList.VERTICAL);
				libMultiList.setVisibleRowCount(5);
	
				
				for(int j = 1 ; j < SUBJECT.length ; j++) {
					libListModel.addElement(SUBJECT[j]);
				}				

				libScrollList.setBounds(420, y, LIST_WIDTH/2, CPNT_HEIGHT*3);
				libScrollList.setVisible(false);
				
				libQryTab.add(libScrollList);
			}
			
			y += CPNT_HEIGHT + CPNT_INDENT;
		}		
		
		
		// Add Book
		libButton[0].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < libButton.length ; i++) {
					if(i == 0) {
						libButton[i].setEnabled(false);
					} else {
						libButton[i].setEnabled(true);						
					}
				}
				
				action = "add book";	
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields	
				libSubjList.setVisible(false);	
				libScrollList.setVisible(true);
				LibView.addBook(libLabl, libText);
			}
		});		
		
		// Remove Book 
		libButton[1].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < libButton.length ; i++) {
					if(i == 1) {
						libButton[i].setEnabled(false);
					} else {
						libButton[i].setEnabled(true);						
					}
				}
				
				action = "remove book";	
				clearFields();				
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields	
				libSubjList.setVisible(false);	
				libScrollList.setVisible(false);				
				LibView.removeBook(libLabl, libText);
			}
		});		

		// Remove Borrower 
		libButton[2].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < libButton.length ; i++) {
					if(i == 2) {
						libButton[i].setEnabled(false);
					} else {
						libButton[i].setEnabled(true);						
					}
				}
				
				action = "remove borrower";	
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields		
				libSubjList.setVisible(false);		
				libScrollList.setVisible(false);				
				LibView.removeBorrower(libLabl, libText);
			}
		});		

		// Generate Report 1
		libButton[3].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < libButton.length ; i++) {
					if(i == 3) {
						libButton[i].setEnabled(false);
					} else {
						libButton[i].setEnabled(true);						
					}
				}
				
				action = "generate report 1";	
				mnEditItem[0].setEnabled(false);		// Disable Clear Fields	
				libSubjList.setVisible(true);
				libScrollList.setVisible(false);				
				LibView.generateReport1(libLabl, libText);	
			}
		});			
		
		// Generate Report 2
		libButton[4].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for (int i = 0; i < libButton.length ; i++) {
					if(i == 4) {
						libButton[i].setEnabled(false);
					} else {
						libButton[i].setEnabled(true);						
					}
				}
				
				action = "generate report 2";	
				clearFields();
				mnEditItem[0].setEnabled(true);		// Enable Clear Fields		
				libSubjList.setVisible(false);		
				libScrollList.setVisible(false);				
				LibView.generateReport2(libLabl, libText);				
			}
		});				

		// Execute
		libButton[5].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(sql == null || sql.isConnected() == false) {
					JOptionPane.showMessageDialog(frame,
						    "No connection to database!",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);										
					return;
				}
				
				
				
				Boolean check = true;
				if(action == "add book") {
					try {
						check = LibExec.addBook(libLabl, libText, libTable, libMultiList, libListModel, frame, sql);

						if(check == true) {
							JOptionPane.showMessageDialog(frame,
							"Book Added!");							
							return;
						}
						
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					}					
				} else if (action == "remove book") {
					try {
						check = LibExec.removeBook(libLabl, libText, libTable, sql);
						
						if(check == true) {
							JOptionPane.showMessageDialog(frame,
							"Book Removed!");							
							return;
						}
						
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					}					
				} else if (action == "remove borrower") {
					try {
						check = LibExec.removeBorrower(libLabl, libText, libTable, sql);
						
						if(check == true) {
							JOptionPane.showMessageDialog(frame,
							"Borrower Removed!");							
							return;
						}
						
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					}										
				} else if (action == "generate report 1") {
					try {
						if(LibExec.generateReport1(libLabl, libText, libSubjList, libTable, frame, sql) == true) {
							JOptionPane.showMessageDialog(frame,
							"Report Generated! See Results tab.");
						}
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
						e.printStackTrace();
					}					
				} else if (action == "generate report 2") {
					try {
						check = LibExec.generateReport2(libLabl, libText, libTable, frame, sql);
						
						System.out.println("HIIII");
							
						if(check == true) {
							JOptionPane.showMessageDialog(frame,
							"Report Generated! See Results tab.");							
						}
					} catch (NumberFormatException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					} catch (Exception e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}					
				}

				if(check != true) {
					libTable.setVisible(false);
					JOptionPane.showMessageDialog(frame,
						    "Missing input field(s)",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);		
				} else {
					if(libTab.getTabCount() < 2) {
						libTab.addTab("Result", null, libScroll, null);
					}				
					libTable.setVisible(true);
				}

			}
		});			
	}

	private void initClkQryTab () {
		for(int i = 0 ; i < clkButton.length; i++) {
			clkButton[i] = new JButton ();
			clkButton[i].setText(CLK_BUTN[i]);
		}
		
		for(int i = 0; i < callNumberTextFields.length; i++) {
			callNumberTextFields[i] = new JTextField(40);
		}
		
		for(int i = 0; i < copyNumbersTextFields.length; i++) {
			copyNumbersTextFields[i] = new JTextField(10);
		}
		
		userTypeComboBox.addItem(USER_TYPE_FACULTY);
		userTypeComboBox.addItem(USER_TYPE_STAFF);
		userTypeComboBox.addItem(USER_TYPE_STUDENT);
		
		JPanel clerkExecuteButtonPanel = new JPanel();
		JPanel clerkTopButtonPanel = new JPanel();
		final JPanel clerkBodyPanel = new JPanel();
		
		clkQryTab.setLayout(new BorderLayout());
		clkQryTab.add(clerkTopButtonPanel, BorderLayout.NORTH);
		clkQryTab.add(clerkBodyPanel, BorderLayout.CENTER);
		clkQryTab.add(clerkExecuteButtonPanel, BorderLayout.SOUTH);
		
		GroupLayout topButtonGroupLayout = new GroupLayout(clerkTopButtonPanel);
		
		topButtonGroupLayout.setAutoCreateGaps(true);
		topButtonGroupLayout.setAutoCreateContainerGaps(true);
		
		GroupLayout.SequentialGroup topButtonHGroup = topButtonGroupLayout.createSequentialGroup();
		topButtonHGroup.addGroup(topButtonGroupLayout.createParallelGroup()
				.addComponent(clkButton[0])
		);
		topButtonHGroup.addGroup(topButtonGroupLayout.createParallelGroup()
				.addComponent(clkButton[1])
		);
		topButtonHGroup.addGroup(topButtonGroupLayout.createParallelGroup()
				.addComponent(clkButton[2])
		);
		topButtonHGroup.addGroup(topButtonGroupLayout.createParallelGroup()
				.addComponent(clkButton[3])
		);
		topButtonGroupLayout.setHorizontalGroup(topButtonHGroup);
		
		GroupLayout.SequentialGroup topButtonVGroup = topButtonGroupLayout.createSequentialGroup();
		topButtonVGroup.addGroup(topButtonGroupLayout.createParallelGroup(Alignment.BASELINE)
				.addComponent(clkButton[0])
				.addComponent(clkButton[1])
				.addComponent(clkButton[2])
				.addComponent(clkButton[3])
		);
		topButtonGroupLayout.setVerticalGroup(topButtonVGroup);
		
		GroupLayout bottomButtonGroupLayout = new GroupLayout(clerkExecuteButtonPanel);
		
		bottomButtonGroupLayout.setAutoCreateGaps(true);
		bottomButtonGroupLayout.setAutoCreateContainerGaps(true);
		
		GroupLayout.SequentialGroup bottomButtonHGroup = bottomButtonGroupLayout.createSequentialGroup();
		bottomButtonHGroup.addGroup(bottomButtonGroupLayout.createParallelGroup(Alignment.TRAILING)
				.addComponent(clkButton[4])
		);
		bottomButtonGroupLayout.setHorizontalGroup(bottomButtonHGroup);
		
		GroupLayout.SequentialGroup bottomButtonVGroup = bottomButtonGroupLayout.createSequentialGroup();
		bottomButtonVGroup.addGroup(bottomButtonGroupLayout.createParallelGroup(Alignment.BASELINE)
				.addComponent(clkButton[4])
		);
		bottomButtonGroupLayout.setVerticalGroup(bottomButtonVGroup);

		// Add Borrower 
		clkButton[0].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				action = ADD_BORROWER;
				LibView.createClerkAddBorrowerLayout(clerkBodyPanel, sinOrStudentNumberTextField, nameTextField, passwordTextField, addressTextField, phoneNumberTextField, emailAddressTextField, expiryDateTextField, userTypeComboBox);
				for (int i=0; i<clkButton.length; i++) {
					clkButton[i].setEnabled(i != 0);
				}
			}
		});
		
		// Check-out Item 
		clkButton[1].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				action = CHECK_OUT_ITEM;
				LibView.createClerkCheckOutItemLayout(clerkBodyPanel, borrowerIdTextField, callNumberTextFields, copyNumbersTextFields);
				for (int i=0; i<clkButton.length; i++) {
					clkButton[i].setEnabled(i != 1);
				}
			}
		});		
		
		// Process Return 
		clkButton[2].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				action = PROCESS_RETURN;
				LibView.createClerkProcessReturnLayout(clerkBodyPanel, callNumberTextFields, copyNumbersTextFields);
				for (int i=0; i<clkButton.length; i++) {
					clkButton[i].setEnabled(i != 2);
				}
			}
		});		
		
		// Check Overdue
		clkButton[3].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				action = CHECK_OVERDUE;
				LibView.createClerkCheckOverdueLayout(clerkBodyPanel);
				for (int i=0; i<clkButton.length; i++) {
					clkButton[i].setEnabled(i != 3);
				}
			}
		});		

		// Execute
		clkButton[4].addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Boolean check = true;
				if(sql == null || sql.isConnected() == false) {
					JOptionPane.showMessageDialog(frame,
						    "No connection to database!",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);										
					return;
				}
				
				if(action.compareTo(ADD_BORROWER) == 0) {
					String sinOrStudentNumber = sinOrStudentNumberTextField.getText().trim();
					String name = nameTextField.getText().trim();
					String password = String.valueOf(passwordTextField.getPassword()).trim();
					String address = addressTextField.getText().trim();
					String phoneNumber = phoneNumberTextField.getText().trim();
					String emailAddress = emailAddressTextField.getText().trim();

					String userType = ((String)userTypeComboBox.getSelectedItem()).trim();
					
					ClerkActions clerkActions = new ClerkActions();
					try {
						Date timeStamp = (expiryDateTextField.getText().trim().isEmpty()? null : Date.valueOf(expiryDateTextField.getText().trim())); // assume format = "YYYY-MM-DD" (all number form)
						
						if (!sinOrStudentNumber.isEmpty() && !name.isEmpty() && !password.isEmpty() && !address.isEmpty() && !phoneNumber.isEmpty() && timeStamp != null && !emailAddress.isEmpty()) {
							Integer.parseInt(sinOrStudentNumber);
								
							clerkActions.addBorrower(sinOrStudentNumber, name, password, address, phoneNumber, emailAddress, timeStamp, userType);
						} else {
							displayErrorAlert(31001);
						}
					} catch (SQLException e) {
						e.printStackTrace();
					} catch(NumberFormatException e) {
						displayErrorAlert(31003);
					} catch(IllegalArgumentException e) {
						displayErrorAlert(31004);
					}

					// Display Data in JTable
					
				} else if (action.compareTo(CHECK_OUT_ITEM) == 0) {
					String borrowerId = borrowerIdTextField.getText().trim();
					ArrayList<String[]> callNumbersAndCopyNumbers = new ArrayList<String[]>();
					
					for (int i=0; i<callNumberTextFields.length; i++) {
						String callNumber = callNumberTextFields[i].getText().trim();
						String copyNumber = copyNumbersTextFields[i].getText().trim();
						if (!callNumber.isEmpty() && !copyNumber.isEmpty()) {
							callNumbersAndCopyNumbers.add(new String[] {callNumber,copyNumber});
						}
					}					

					ClerkActions clerkActions = new ClerkActions();
					try {
						if (!borrowerId.isEmpty() && !callNumbersAndCopyNumbers.isEmpty()) {
							ArrayList<String[]> validCallNumbers = new ArrayList<String[]>();
							ArrayList<String[]> invalidCallNumbers = new ArrayList<String[]>();

							for(int i = 0; i < callNumbersAndCopyNumbers.size(); i++) {
								String[] curCallNumCopyNum = callNumbersAndCopyNumbers.get(i);

								if (isCorrectCallNumberFormat(curCallNumCopyNum[CALL_NUMBER_INDEX]) && isCorrectCopyNumberFormat(curCallNumCopyNum[COPY_NUMBER_INDEX])) {
									validCallNumbers.add(curCallNumCopyNum);
								} else {
									invalidCallNumbers.add(curCallNumCopyNum);
								}
							}

							if (invalidCallNumbers.isEmpty()) {
								clerkActions.checkOut(borrowerId, validCallNumbers);
							} else {
								displayErrorAlert(31002);
							}
						} else {
							displayErrorAlert(31001);
						}
					} catch (SQLException e) {
						e.printStackTrace();
					}
				} else if (action.compareTo(PROCESS_RETURN) == 0) {
					ClerkActions clerkActions = new ClerkActions();
					String callNum = callNumberTextFields[0].getText().trim();
					String copyNum = copyNumbersTextFields[0].getText().trim();
					boolean correctCopyNumFormat = isCorrectCopyNumberFormat(copyNum);
					boolean correctCallNumFormat = isCorrectCallNumberFormat(callNum);
					
					if(callNum.compareTo("") == 0 && copyNum.compareTo("") == 0) {
						displayErrorAlert(31001);
					}
					
					if(!correctCallNumFormat && callNum.compareTo("") != 0) {
						displayErrorAlert(33001);
					}
					
					if(!correctCopyNumFormat && copyNum.compareTo("") != 0) {
						displayErrorAlert(33002);
					}
					
					if(correctCopyNumFormat && correctCallNumFormat) {
						int copyNumIntForm = Integer.parseInt(copyNum);
						try {
							clerkActions.processReturn(callNum, copyNumIntForm);
						} catch (SQLException e) {
							e.printStackTrace();
						}
					}
					
				} else if (action.compareTo(CHECK_OVERDUE) == 0) {
					ClerkActions clerkActions = new ClerkActions();
					try {
						LibView.updateClerkCheckOverdueLayout(clerkBodyPanel);
						check = LibExec.checkOverdue(clerkActions, frame, clkTable);
						
						if(check == true) {
							
						} else {
							
						}
						
					} catch (SQLException e) {
						JOptionPane.showMessageDialog(frame,
								e.getMessage(),
							    "Error",
							    JOptionPane.ERROR_MESSAGE);
					}
				}
				
				if(check != true) {
					clkTable.setVisible(false);
					JOptionPane.showMessageDialog(frame,
						    "Missing input field(s)",
						    "Warning",
						    JOptionPane.WARNING_MESSAGE);		
				} else {
					clkTable.setVisible(true);
				}
			}
		});
		
		clkButton[0].doClick();
	}
	
	public void createPopup(String messageShown, String filePathOfIcon, String createDialogueMessage) {
		JFrame frame = getInstance().getFrame();

		JOptionPane pane = new JOptionPane(messageShown);
		ImageIcon imageIcon = new ImageIcon(filePathOfIcon);
		pane.setIcon(imageIcon);
		JDialog dialog = pane.createDialog(createDialogueMessage);
		dialog.setLocation(frame.getX() + (frame.getWidth() - dialog.getWidth()) / 2, frame.getY() + (frame.getHeight() - dialog.getHeight()) / 2);
		dialog.setVisible(true);
	}
	
	private void displayErrorAlert(int errorCode) {
		String filePathOfIcon = "assets/warning_icon.png";
		String dialogueMessage = "Warning";
		String message = "";
		
		switch(errorCode) {
		case 31001:
			message = "Missing input field(s).";
			createPopup(message, filePathOfIcon, dialogueMessage);
			break;
			
		case 31002:
			message = "At least one call number has an incorrect format. \nPlease try again.";
			createPopup(message, filePathOfIcon, dialogueMessage);		
			break;
			
		case 31003:
			message = "The value entered for SIN/Student number is not an integer. \nPlease try again.";
			createPopup(message, filePathOfIcon, dialogueMessage);		
			break;
			
		case 31004:
			message = "The value entered for Expiry Date is not in the correct format.  The format should be YYYY-MM-DD. \nPlease try again.";
			createPopup(message, filePathOfIcon, dialogueMessage);		
			break;
			
		case 33001:
			message = "Incorrect call number format.  \nPlease try again.";
			createPopup(message, filePathOfIcon, dialogueMessage);	
			break;
			
		case 33002:
			message = "Incorrect copy number format.  \nPlease try again.";
			createPopup(message, filePathOfIcon, dialogueMessage);				
			break;
		}
	}
	
	private boolean isCorrectCopyNumberFormat(String copyNumber) {
		boolean result = true;
		
		try {
			Integer.parseInt(copyNumber);
		} catch (Exception e) {
			result = false;
		}
		
		return result;
	}
	
	private boolean isCorrectCallNumberFormat(String callNumber) {
		boolean callNumberIsValid = true;
		String[] callNumberSplit = callNumber.split(" ");
		
		if (callNumberSplit.length < 3) {
			callNumberIsValid = false;
		} else {
			if (callNumberSplit[0].isEmpty()) {
				callNumberIsValid = false;
			}
			
			if (callNumberSplit[1].isEmpty()) {
				callNumberIsValid = false;
			}
			
			if (callNumberSplit[2].isEmpty()) {
				callNumberIsValid = false;
			} else {
				try {
					Integer.parseInt(callNumberSplit[2]);
				} catch (Exception e) {
					callNumberIsValid = false;
				}
			}
		}
		
		return callNumberIsValid;
	}
}